package com.lyj.system.service.exam.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lyj.common.core.constants.Constants;
import com.lyj.common.core.enums.ResultCode;
import com.github.pagehelper.PageHelper;
import com.lyj.security.exception.ServiceException;
import com.lyj.system.domain.exam.Exam;
import com.lyj.system.domain.exam.ExamQuestion;
import com.lyj.system.domain.exam.dto.ExamAddDTO;
import com.lyj.system.domain.exam.dto.ExamEditDTO;
import com.lyj.system.domain.exam.dto.ExamQueryDTO;
import com.lyj.system.domain.exam.dto.ExamQuestAddDTO;
import com.lyj.system.domain.exam.vo.ExamDetailVO;
import com.lyj.system.domain.exam.vo.ExamVO;
import com.lyj.system.domain.question.Question;
import com.lyj.system.domain.question.vo.QuestionVO;
import com.lyj.system.manager.ExamCacheManager;
import com.lyj.system.mapper.exam.ExamMapper;
import com.lyj.system.mapper.exam.ExamQuestionMapper;
import com.lyj.system.mapper.question.QuestionMapper;
import com.lyj.system.service.exam.ExamService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: LIUYANJIAO
 * Date: 2025-08-20
 * Time: 23:57
 */
@Service
public class ExamServiceImpl extends ServiceImpl<ExamQuestionMapper, ExamQuestion> implements ExamService {
    @Autowired
    private ExamMapper examMapper;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private ExamQuestionMapper examQuestionMapper;

    @Autowired
    private ExamCacheManager examCacheManager;

    @Override
    public List<?> list(ExamQueryDTO examQueryDTO) {
        PageHelper.startPage(examQueryDTO.getPageNum(),examQueryDTO.getPageSize());
        List<ExamVO> examVOS = examMapper.selectExamList(examQueryDTO);
        return examVOS;
    }

    @Override
    public String add(ExamAddDTO examAddDTO) {
        checkExamSaveParams(examAddDTO,null);
        //插入数据
        Exam exam = new Exam();
        BeanUtils.copyProperties(examAddDTO,exam);
        examMapper.insert(exam);
        return exam.getExamId().toString();
    }


    @Override
    public boolean questionAdd(ExamQuestAddDTO examQuestAddDTO) {
        //首先判断竞赛是否存在
        Exam exam =examIsExist(examQuestAddDTO.getExamId());
        //判断竞赛是否发布
        if (Constants.TRUE.equals(exam.getStatus())) {
            throw new ServiceException(ResultCode.EXAM_IS_PUBLISH);
        }
        //再次判断题目是否存在
        Set<Long> questionIdSet = examQuestAddDTO.getQuestionIdSet();
        if(CollectionUtil.isEmpty(questionIdSet)){
            return true;
        }
        List<Question> questions = questionMapper.selectBatchIds(questionIdSet);
        if(CollectionUtil.isEmpty(questions)||questions.size()<questionIdSet.size()){
            throw new ServiceException(ResultCode.EXAM_NOT_HAS_QUESTION);
        }
        //判断竞赛列表的题目是否为空
        Long l = examQuestionMapper.selectCount(new QueryWrapper<ExamQuestion>().lambda()
                .eq(ExamQuestion::getExamId, examQuestAddDTO.getExamId()));
        //插入
        int num = 1;
        if(l>0){
            num = examQuestionMapper.getMaxQuestionOrderByExamId(examQuestAddDTO.getExamId())+1;
        }

        List<ExamQuestion> examQuestionList = new ArrayList<>();
        for (Long questionId : questionIdSet) {
            ExamQuestion examQuestion = new ExamQuestion();
            examQuestion.setExamId(exam.getExamId());
            examQuestion.setQuestionId(questionId);
            examQuestion.setQuestionOrder(num++);
            examQuestionList.add(examQuestion);
        }
        return saveBatch(examQuestionList);
    }

    @Override
    public int questionDelete(Long examId, Long questionId) {
        //判断竞赛是否存在
        Exam exam = examIsExist(examId);

        if (Constants.TRUE.equals(exam.getStatus())) {
            throw new ServiceException(ResultCode.EXAM_IS_PUBLISH);
        }

        //删除
        return examQuestionMapper.delete(new QueryWrapper<ExamQuestion>().lambda()
                .eq(ExamQuestion::getExamId,examId)
                .eq(ExamQuestion::getQuestionId,questionId));
    }

    @Override
    public ExamDetailVO detail(Long examId) {
        ExamDetailVO examDetailVO = new ExamDetailVO();
        //首先获得竞赛信息
        Exam exam = examIsExist(examId);
        BeanUtils.copyProperties(exam,examDetailVO);
        //再获得题目列表
        List<QuestionVO> questionVOS = examQuestionMapper.selectQuestionList(examId);
        examDetailVO.setExamQuestionList(questionVOS);
        return examDetailVO;
    }

    @Override
    public int edit(ExamEditDTO examEditDTO) {
        Exam exam = examIsExist(examEditDTO.getExamId());
        //判断是否已发布
        if (Constants.TRUE.equals(exam.getStatus())) {
            throw new ServiceException(ResultCode.EXAM_IS_PUBLISH);
        }
        //检查各个元素是否安全
        checkExamSaveParams(examEditDTO,examEditDTO.getExamId());

        exam.setTitle(examEditDTO.getTitle());
        exam.setStartTime(examEditDTO.getStartTime());
        exam.setEndTime(examEditDTO.getEndTime());
        return examMapper.updateById(exam);
    }

    @Override
    public int delete(Long examId) {
        //首先删除竞赛中的题目
        Exam exam = examIsExist(examId);
           //判断是否已发布
        if (Constants.TRUE.equals(exam.getStatus())) {
            throw new ServiceException(ResultCode.EXAM_IS_PUBLISH);
        }
        examQuestionMapper.delete(new QueryWrapper<ExamQuestion>().lambda()
                .eq(ExamQuestion::getExamId,examId));
        //再删除竞赛
        return examMapper.deleteById(examId);
    }

    @Override
    public int publish(Long examId) {
        Exam exam = examIsExist(examId);
        //判断发布时间是不是超过竞赛结束时间
        if(exam.getEndTime().isBefore(LocalDateTime.now())){
            throw new ServiceException(ResultCode.EXAM_IS_FINISH);
        }
        //判断竞赛中是否有题目
        Long l = examQuestionMapper.selectCount(new QueryWrapper<ExamQuestion>().lambda()
                .eq(ExamQuestion::getExamId, examId));
        if(l==null||l<=0){
            throw new ServiceException(ResultCode.EXAM_NOT_HAS_QUESTION);
        }
        exam.setStatus(Constants.TRUE);
        //将竞赛存储到redis中
        examCacheManager.addCache(exam);
        return examMapper.updateById(exam);
    }

    @Override
    public int cancelPublish(Long examId) {
        Exam exam = examIsExist(examId);
        //判断发布时间是不是超过竞赛结束时间
        if(exam.getEndTime().isBefore(LocalDateTime.now())){
            throw new ServiceException(ResultCode.EXAM_IS_FINISH);
        }
        exam.setStatus(Constants.FALSE);
        //将竞赛从redis中删除
        examCacheManager.deleteCache(examId);
        return examMapper.updateById(exam);
    }


    private Exam examIsExist(Long examId) {
        Exam exam = examMapper.selectOne(new QueryWrapper<Exam>().lambda().eq(Exam::getExamId, examId));

        if(exam == null){
            throw new ServiceException(ResultCode.FAILED_NOT_EXISTS);
        }
        return exam;
    }
    private void checkExamSaveParams(ExamAddDTO examAddDTO,Long examId) {
        //首先判断该竞赛是否已经存在
        List<Exam> exams = examMapper.selectList(new QueryWrapper<Exam>().lambda()
                .eq(Exam::getTitle, examAddDTO.getTitle())
                .ne(examId!=null,Exam::getExamId,examId));
        if(CollectionUtil.isNotEmpty(exams)){
            throw new ServiceException(ResultCode.FAILED_ALREADY_EXISTS);
        }
        //时间要求 开始时间要早于当前时间
        //        结束时间要晚于开始时间
        if(examAddDTO.getStartTime().isBefore(LocalDateTime.now())){
            throw new ServiceException(ResultCode.EXAM_START_TIME_BEFORE_CURRENT_TIME);
        }
        if(examAddDTO.getEndTime().isBefore(examAddDTO.getStartTime())){
            throw new ServiceException(ResultCode.EXAM_START_TIME_AFTER_END_TIME);
        }
    }

}
